import NearNode from "./interface/NearNode";
import { GridSystem, MyRect, Block } from "./Index";
import gsap from 'gsap'

class PathSearch {

    coordList: NearNode[];  // 路径点集合
    originNode: NearNode;  // 起点
    targetNode: NearNode;  // 终点
    biasX: boolean;  // x轴偏向
    biasY: boolean;  // y轴偏向
    step: number;  // 跑步
    constructor(originNode: NearNode, targetNode: NearNode) {
        this.coordList = [];
        this.originNode = originNode;
        this.targetNode = targetNode;
        this.biasX = this.targetNode.x > this.originNode.x;  // 偏左
        this.biasY = this.targetNode.y > this.originNode.y;  // 偏上
        this.step = 0;
    }

    // 获取当前节点附近的6个点,分别是 左, 上, 右, 下, 左上, 右上, 右下, 左下
    getNearNodes(originNode: NearNode) {
        let leftNode = {
            name: "left",
            x: originNode.x - 1,
            y: originNode.y,
            g: !this.biasX ? .9 : 1,
            h: 0,
            f: 0,
        };
        this.setDistProp(leftNode);


        let leftTopNode = {
            name: "left-top",
            x: originNode.x - 1,
            y: originNode.y - 1,
            g: 1.4,
            h: 0,
            f: 0,
        };
        this.setDistProp(leftTopNode);

        let topNode = {
            name: "top",
            x: originNode.x,
            y: originNode.y - 1,
            g: !this.biasY ? .9 : 1,
            h: 0,
            f: 0,
        };
        this.setDistProp(topNode);

        let topRightNode = {
            name: "top-right",
            x: originNode.x + 1,
            y: originNode.y + 1,
            g: 1.4,
            h: 0,
            f: 0,
        };
        this.setDistProp(topRightNode);

        let rightNode = {
            name: "right",
            x: originNode.x + 1,
            y: originNode.y,
            g: this.biasX ? .9 : 1,
            h: 0,
            f: 0,
        };
        this.setDistProp(rightNode);

        let rightBottomNode = {
            name: "right-bottom",
            x: originNode.x + 1,
            y: originNode.y - 1,
            g: 1.4,
            h: 0,
            f: 0,
        };
        this.setDistProp(rightBottomNode);

        let bottomNode = {
            name: "bottom",
            x: originNode.x,
            y: originNode.y + 1,
            g: !this.biasY ? .9 : 1,
            h: 0,
            f: 0,
        };
        this.setDistProp(bottomNode);

        let leftBottomNode = {
            name: "left-bottom",
            x: originNode.x - 1,
            y: originNode.y - 1,
            g: 1.4,
            h: 0,
            f: 0,
        };
        this.setDistProp(leftBottomNode);
        // leftTopNode, rightBottomNode, topRightNode, leftBottomNode
        return [leftNode, topNode, rightNode, bottomNode,]

    }

    // 递归找离目标点最近的点,push到数组当中
    pushNearNode(fn: Function) {
        let nearNodeArr = this.getNearNodes(this.originNode);
        let minFNode = null;   // 离目标最近的点
        let obstacle = GridSystem.gls.blocks.filter(fBlock => fBlock.isObstacle);  // 障碍物s
        for (let index = 0; index < nearNodeArr.length; index++) {
            const node = nearNodeArr[index];
            let lastCoordNode = this.coordList[this.coordList.length - 2] || { x: 0, y: 0 };
            if (GridSystem.gls.hasBlockByGridCoord(obstacle, node.x, node.y) || (node.x == lastCoordNode.x && node.y == lastCoordNode.y)) {
                continue;
            }
            if (!minFNode) {
                minFNode = node;
            } else if (node.f <= minFNode.f) {
                minFNode = node;
            }
        }
        if (minFNode) {
            this.coordList.push(minFNode);
            this.originNode = minFNode;

            // let rectGrid = new MyRect(0, 0, 4, 4);
            // rectGrid.setGridCoord(minFNode.x, minFNode.y);
            // rectGrid.fill = "#ffd591";
            // rectGrid.cbSelect = false;
            // GridSystem.gls.add(rectGrid)

            if (minFNode.x == this.targetNode.x && minFNode.y == this.targetNode.y) {
                this.coordList.push(this.targetNode);
                fn && fn();
            } else {
                // setTimeout(() => {
                this.pushNearNode(fn);
                // }, 300)
            }
        }
    }

    run2Target(originBlock: Block) {
        let pos = GridSystem.gls.getPosByGridCoord(this.coordList[this.step].x, this.coordList[this.step].y);
        let that = this;

        gsap.to(originBlock, {
            duration: .35,
            x: pos.x,
            y: pos.y,
            onUpdate() {
                // GridSystem.gls.drawLineGrid();
            },
            onComplete() {
                that.step++;
                if (that.step <= that.coordList.length - 1) {
                    that.run2Target(originBlock);
                }
            }
        })

    }

    setDistProp(node: NearNode) {
        if (!node.g) {
            node.g = 0;
        }
        node.h = Math.abs(this.targetNode.x - node.x) + Math.abs(this.targetNode.y - node.y);
        node.f = node.g + node.h;
    }
}

export default PathSearch;